﻿using System;

namespace TypeClassSample.Monad
{
	public class Option<T>
	{
		public class NothingVar : Option<T>
		{
			private NothingVar() { }
			public static readonly NothingVar Instance = new NothingVar();
		}

		public class JustVar : Option<T>
		{
			readonly T value;
			public JustVar(T value)
			{
				this.value = value;
			}

			public T Value { get { return value; } }
		}

		public static readonly Option<T> Nothing = NothingVar.Instance;

		public static Option<T> Return(T a) { return new JustVar(a); }
		public Option<B> Bind<B>(Func<T, Option<B>> func)
		{
			var just = this as JustVar;
			if (just == null) return Option<B>.Nothing;
			return func(just.Value);
		}

		public void Iter(Action<T> action)
		{
			var just = this as JustVar;
			if (just == null) return;
			action(just.Value);
		}
	}

	public static class Option
	{
		public static Option<T> Just<T>(T value) { return new Option<T>.JustVar(value); }
	}
}
